package edu.utdallas_elearn_calendar.utdallas_elearn_calendar_app;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import edu.utdallas_elearn_calendar.utdallas_elearn_calendar_db.CalDbAdapter;

import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.app.ProgressDialog;
import android.database.Cursor;
import android.os.Bundle; 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View; 
import android.widget.TextView;
import android.content.SharedPreferences; 
import android.widget.Toast;

public class ElearningPortal extends Activity implements Runnable { 
	private static final String LOG_CONNECTION = "CONNECTION";
    private static final String LOG_LOGINPROCESS = "LOGIN_PROCESS";
    private static final int LOGIN_ATTEMPTS = 5;
	private static final int UPDATE_SETTINGS = 0;
	private SharedPreferences prefs;
	private TextView mUserNameText;
	private TextView mLinkText;
	private String username;
	private String password;
	private String elearningLink;
	private ProgressDialog pd;
	private CalDbAdapter mDbHelper;

	public void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState); 
		mDbHelper = new CalDbAdapter(this);
		mDbHelper.open();
        setContentView(R.layout.elearning_portal);  

        prefs = new ObscuredSharedPreferences(  
        	    this, this.getSharedPreferences("preferences", Context.MODE_PRIVATE) );
        mUserNameText = (TextView) findViewById(R.id.tvUserName);
        mLinkText = (TextView) findViewById(R.id.tvLink);
        populateData();
    } 


	private void populateData() {		
		username = prefs.getString("UserName", "");
		password = prefs.getString("PassWord", "");
		elearningLink = prefs.getString("ElearningLink", ""); 
		
		mUserNameText.setText(username);
		mLinkText.setText(elearningLink);
		
		setLastSyncText();
		
		// if we have a password then try to sync
		if (validPrefs()) {
			syncBtnClicked(this.getCurrentFocus());
		} 
	}

	private boolean validPrefs() {
		int intFieldsMissing = 0;
		
		if(username.length() == 0) {
			intFieldsMissing = intFieldsMissing + 1;
		}	
		if(password.length() == 0) {
			intFieldsMissing = intFieldsMissing + 2;
		}		
		
		if(intFieldsMissing == 1) {
			Toast.makeText(this, "The eLearning username cannot be empty! Please enter the eLearning username.", Toast.LENGTH_LONG).show();
			return false;
		}
		
		if(intFieldsMissing == 2) {
			Toast.makeText(this, "The eLearning password cannot be empty! Please enter the eLearning password.", Toast.LENGTH_LONG).show();
			return false;
		}
		
		if(intFieldsMissing == 3) {
			Toast.makeText(this, "The eLearning username and password cannot be empty! Please enter the eLearning username and password.", Toast.LENGTH_LONG).show();
			return false;
		}
		
		return true;
	}
	
    public void run() {
    	
    	this.getData(); 	
        handler.sendEmptyMessage(0);
    }

	private Handler handler = new Handler() {
	    @Override
	    public void handleMessage(Message msg) {
	        pd.dismiss();
	        finish();
	    }
	};    
    
    public void syncBtnClicked(View view) { 
		if (validPrefs()) {
			pd = ProgressDialog.show(this, "Loading...", "Pulling Calendar", true, false);

			Thread thread = new Thread(this);
			thread.start();
		}
    }
    
    public void settingsBtnClicked(View view) { 
        switch (view.getId()) { 
        case R.id.btnSettings:         
	        Intent i = new Intent(view.getContext(), AskUserPass.class); 
	        startActivityForResult(i, UPDATE_SETTINGS);
		} 
    }
    
    /**
     * onActivityResult is called once the startActivityForResult
     * activity returns
     */
	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {
		super.onActivityResult(requestCode, resultCode, intent);
		populateData();
	}
	
	/**
	 * get the events and classes from the elearning calendar
	 * 
	 */
	public boolean getData()
    {  	
    	
    	try {
    		
    		HttpClient client = null; 
    		client = this.LoginToElearning(0, client);
			if(client == null)
			{
				Log.i(LOG_CONNECTION, "Problem logging into eLearning");
				
				Date d = new Date();
				String hour = String.valueOf(d.getHours());
				String minutes = String.valueOf(d.getMinutes());
				
				if (hour.length() < 2) {
					hour = "0" + hour;
				}
				
				if (minutes.length() < 2) {
					minutes = "0" + minutes;
				}
				
		        String timeStamp = (d.getMonth()+1) + "/" + d.getDate() + "/" + 
		        		(d.getYear()+1900) + " " + hour + ":" + minutes;
		        mDbHelper.insertElearnLog(timeStamp, "Fail");
		        
				return false;
			}
			
			// make call to calendar
			// got the link from a different frame on the main logged in page, will it always be the same??
			//HttpGet request5 = new HttpGet(elearningLink);
			HttpGet request5 = new HttpGet("https://elearning.utdallas.edu/webct/urw/lc5122011.tp0/viewCalendar.dowebct");
			
        	Log.i(LOG_CONNECTION, "-- about to make call to open the calendar --");
			HttpResponse response5 = client.execute(request5);
			HttpEntity entity5 = response5.getEntity();
			if(entity5 == null)
			{
				//tv.setText("error on fifth page response");
				Log.i(LOG_CONNECTION, "error on fifth page response");
				return false;
			}
			
			// look for '<title>Calendar</title>' to ensure we made it to the calendar
			String sHTML1 = "";
			sHTML1 = this.parseHtmlFromEntity(entity5);			
			int nIndex = sHTML1.indexOf("Key:");
			if(nIndex < 0 && sHTML1.indexOf("<title>Calendar</title>") > 0)
			{
				//tv.setText("error on fifth page response - 2");
				Log.i(LOG_CONNECTION, "error on fifth page response - 2");
				return false;
			}
			Log.i(LOG_CONNECTION, "-- successfully got to the calendar --");
			
			ArrayList<UniversityClass> listClasses = new ArrayList<UniversityClass>();
			listClasses = this.parseUnivClassesFromText(nIndex, sHTML1);
			
			
			for(UniversityClass c : listClasses)
			{				
				c.UniversityClassId = mDbHelper.insertClass(c.Prefix, c.ClassNumber, c.ClassSection, c.Title);
				mDbHelper.insertClassDetail(c.UniversityClassId, c.Semester, "", "", "");
			}
			
					
			// which days have events on them
			int[] dayArray = findDaysWithEvents(sHTML1);		
						
	    	Date today = new Date();
	    	String linkStart = "https://elearning.utdallas.edu/webct/urw/lc5122011.tp0/viewDay.dowebct?month=" + 
	    			(today.getMonth()) + "&day=";
	    	String linkEnd = "&year=" + (today.getYear()+1900);
	    	
	    	
	    	// go through the days that have events and pull them
	    	for(int i=0; i<dayArray.length; i++) {
	    		if (dayArray[i]!=0) {
	    			// get entity (linkStart + dayArray[i] + linkEnd)
	    			HttpGet request6 = new HttpGet(linkStart + dayArray[i] + linkEnd);
//	    			Log.i(LOG_CONNECTION, linkStart + dayArray[i] + linkEnd);
	            	Log.i(LOG_CONNECTION, "-- about to make call to open day " + dayArray[i] + " --" );
	    			HttpResponse response6 = client.execute(request6);
	    			HttpEntity entity6 = response6.getEntity();
	    			if(entity6 == null)
	    			{
	    				Log.i(LOG_CONNECTION, "error on day page response");
	    				return false;
	    			}
	    			
	    			// look for '<ul class=\"calendarlist calendarday\">' to ensure we made it to the day calendar
	    			String sHTML6 = "";
	    			sHTML6 = this.parseHtmlFromEntity(entity6);	
	    			if(sHTML1.indexOf("<ul class=\"calendarlist calendarday\">") > 0)
	    			{
	    				Log.i(LOG_CONNECTION, "error on calendar day page response - 2");
	    				return false;
	    			}
	    			Log.i(LOG_CONNECTION, "-- successfully got to the calendar day --");	    			
	    			
	    			ArrayList<UnivClassEvent> listEvents = new ArrayList<UnivClassEvent>();
	    			listEvents = new ArrayList<UnivClassEvent>();
	    			
	    			Date dy = new Date();
	    			dy.setDate(dayArray[i]);
	    			listEvents = parseEventFromDay(listClasses, sHTML6, dy);					
    			
	    			for(UnivClassEvent uce : listEvents)
	    			{	    	
	    				
	    				String year = String.valueOf(uce.DueDate.getYear()+1900);
	    				String month = String.valueOf(uce.DueDate.getMonth()+1);
	    				String day = String.valueOf(uce.DueDate.getDate());
	    				String hour = String.valueOf(uce.DueDate.getHours());
	    				String minutes = String.valueOf(uce.DueDate.getMinutes());
	    				
	    				if (month.length() < 2) {
	    					month = "0" + month;
	    				}
	    				
	    				if (day.length() < 2) {
	    					day = "0" + day;
	    				}
	    				
	    				if (hour.length() < 2) {
	    					hour = "0" + hour;
	    				}
	    				
	    				if (minutes.length() < 2) {
	    					minutes = "0" + minutes;
	    				}
	    				
	    				String dueDate = year + "-" + month + "-" + day + " " + hour + ":" + minutes;
	    				
	    				uce.EventId = mDbHelper.insertEvent(uce.ClassId, uce.EventTypeId, uce.Name,
	    						dueDate, uce.RecurringType);
	    			}
   			
	    		}
	    	}
	    	
	    	// if the next month is approaching then pull next months events
	    	if (today.getDay() > 1) { 
	    		// calculate the next month's date
				int cal_month = today.getMonth();
				
				if (cal_month == 11) { 
					cal_month = 0;
					today.setYear(today.getYear()+1);
				} else {
					cal_month = cal_month + 1;
				}
				
		    	today.setMonth(cal_month);
		    	
				// make call to calendar
				// got the link from a different frame on the main logged in page, will it always be the same??
				//HttpGet request7 = new HttpGet("/webct/urw/lc5122011.tp0/viewMonth.dowebct?year=2012&amp;month=0");
				HttpGet request7 = new HttpGet("https://elearning.utdallas.edu/webct/urw/lc5122011.tp0/viewMonth.dowebct?year=" + 
						(today.getYear()+1900) + "&month=" + today.getMonth());
				
	        	Log.i(LOG_CONNECTION, "-- about to make call to open the calendar --");
				HttpResponse response7 = client.execute(request7);
				HttpEntity entity7 = response7.getEntity();
				if(entity7 == null)
				{
					//tv.setText("error on seventh page response");
					Log.i(LOG_CONNECTION, "error on seventh page response");
					return false;
				}
				
				// look for '<title>Calendar</title>' to ensure we made it to the calendar
				sHTML1 = "";
				sHTML1 = this.parseHtmlFromEntity(entity7);
				nIndex = -1;
				nIndex = sHTML1.indexOf("Key:");
				if(nIndex < 0 && sHTML1.indexOf("<title>Calendar</title>") > 0)
				{
					//tv.setText("error on seventh page response - 2");
					Log.i(LOG_CONNECTION, "error on seventh page response - 2");
					return false;
				}
				Log.i(LOG_CONNECTION, "-- successfully got to the calendar --");	    		
	    		
	    		
		    	// which days have events on them
				dayArray = findDaysWithEvents(sHTML1);		
				

		    	linkStart = "https://elearning.utdallas.edu/webct/urw/lc5122011.tp0/viewDay.dowebct?month=" + 
		    			(today.getMonth()) + "&day=";
		    	linkEnd = "&year=" + (today.getYear()+1900);
		    	
		    	
		    	// go through the days that have events and pull them
		    	for(int i=0; i<dayArray.length; i++) {
		    		if (dayArray[i]!=0) {
		    			// get entity (linkStart + dayArray[i] + linkEnd)
		    			HttpGet request6 = new HttpGet(linkStart + dayArray[i] + linkEnd);
	//	    		    			Log.i(LOG_CONNECTION, linkStart + dayArray[i] + linkEnd);
		            	Log.i(LOG_CONNECTION, "-- about to make call to open day " + dayArray[i] + " --" );
		    			HttpResponse response6 = client.execute(request6);
		    			HttpEntity entity6 = response6.getEntity();
		    			if(entity6 == null)
		    			{
		    				Log.i(LOG_CONNECTION, "error on day page response");
		    				return false;
		    			}
		    			
		    			// look for '<ul class=\"calendarlist calendarday\">' to ensure we made it to the day calendar
		    			String sHTML6 = "";
		    			sHTML6 = this.parseHtmlFromEntity(entity6);	
		    			if(sHTML1.indexOf("<ul class=\"calendarlist calendarday\">") > 0)
		    			{
		    				Log.i(LOG_CONNECTION, "error on calendar day page response - 2");
		    				return false;
		    			}
		    			Log.i(LOG_CONNECTION, "-- successfully got to the calendar day --");	    			
		    			
		    			ArrayList<UnivClassEvent> listEvents = new ArrayList<UnivClassEvent>();
		    			listEvents = new ArrayList<UnivClassEvent>();
		    			
		    			Date dy = new Date();
		    			dy.setMonth(today.getMonth());
		    			dy.setYear(today.getYear());
		    			dy.setDate(dayArray[i]);
		    			listEvents = parseEventFromDay(listClasses, sHTML6, dy);					
	    			
		    			for(UnivClassEvent uce : listEvents)
		    			{	    	
		    				
		    				String year = String.valueOf(uce.DueDate.getYear()+1900);
		    				String month = String.valueOf(uce.DueDate.getMonth()+1);
		    				String day = String.valueOf(uce.DueDate.getDate());
		    				String hour = String.valueOf(uce.DueDate.getHours());
		    				String minutes = String.valueOf(uce.DueDate.getMinutes());
		    				
		    				if (month.length() < 2) {
		    					month = "0" + month;
		    				}
		    				
		    				if (day.length() < 2) {
		    					day = "0" + day;
		    				}
		    				
		    				if (hour.length() < 2) {
		    					hour = "0" + hour;
		    				}
		    				
		    				if (minutes.length() < 2) {
		    					minutes = "0" + minutes;
		    				}
		    				
		    				String dueDate = year + "-" + month + "-" + day + " " + hour + ":" + minutes;
		    				
		    				uce.EventId = mDbHelper.insertEvent(uce.ClassId, uce.EventTypeId, uce.Name,
		    						dueDate, uce.RecurringType);
		    			}
	   			
		    		}
		    	}
	    	}
	    	

			this.LogoutElearning(client);

			Date d = new Date();
			String hour = String.valueOf(d.getHours());
			String minutes = String.valueOf(d.getMinutes());
			
			if (hour.length() < 2) {
				hour = "0" + hour;
			}
			
			if (minutes.length() < 2) {
				minutes = "0" + minutes;
			}
			
	        String timeStamp = (d.getMonth()+1) + "/" + d.getDate() + "/" + 
	        		(d.getYear()+1900) + " " + hour + ":" + minutes;
	        mDbHelper.insertElearnLog(timeStamp, "Success");
	        
			return true;
			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			Log.e("GETDATA", "getData() - client protocol exception: " + e.getMessage());
			
			Date d = new Date();
			String hour = String.valueOf(d.getHours());
			String minutes = String.valueOf(d.getMinutes());
			
			if (hour.length() < 2) {
				hour = "0" + hour;
			}
			
			if (minutes.length() < 2) {
				minutes = "0" + minutes;
			}
			
	        String timeStamp = (d.getMonth()+1) + "/" + d.getDate() + "/" + 
	        		(d.getYear()+1900) + " " + hour + ":" + minutes;
	        mDbHelper.insertElearnLog(timeStamp, "Fail");
	        
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			Log.e("GETDATA", "getData() - IO exception: " + e.getMessage());
			
			Date d = new Date();
			String hour = String.valueOf(d.getHours());
			String minutes = String.valueOf(d.getMinutes());
			
			if (hour.length() < 2) {
				hour = "0" + hour;
			}
			
			if (minutes.length() < 2) {
				minutes = "0" + minutes;
			}
			
	        String timeStamp = (d.getMonth()+1) + "/" + d.getDate() + "/" + 
	        		(d.getYear()+1900) + " " + hour + ":" + minutes;
	        mDbHelper.insertElearnLog(timeStamp, "Fail");
	        
			return false;
		} catch (Exception e)	{
			e.printStackTrace();
			Log.e("GETDATA", "getData() - general exception: " + e.getMessage());
			
			Date d = new Date();
			String hour = String.valueOf(d.getHours());
			String minutes = String.valueOf(d.getMinutes());
			
			if (hour.length() < 2) {
				hour = "0" + hour;
			}
			
			if (minutes.length() < 2) {
				minutes = "0" + minutes;
			}
			
	        String timeStamp = (d.getMonth()+1) + "/" + d.getDate() + "/" + 
	        		(d.getYear()+1900) + " " + hour + ":" + minutes;
	        mDbHelper.insertElearnLog(timeStamp, "Fail");
	        
			return false;
		}

    }


    private HttpClient LoginToElearning(int nAttemptedLogins, HttpClient client)
    {
    	//HttpClient client = null;
    	try
    	{	
    		if(nAttemptedLogins%3 == 0)
    		{
    			Thread.currentThread();
				Thread.sleep(2000);
    		}
    		client = new DefaultHttpClient();
	    	HttpGet request1 = new HttpGet("https://elearning.utdallas.edu/webct/entryPageIns.dowebct");
	    	//HttpGet request1 = new HttpGet("https://elearning.utdallas.edu/webct/logonDisplay.dowebct");
	    	
			// execute request for first page, which provides us with connection parameters
	    	Log.i(LOG_CONNECTION, "-- about to execute first request to eLearning --");
			HttpResponse response1 = client.execute(request1);
			HttpEntity entity1 = response1.getEntity();
			if(entity1 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error in connecting.. 1");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			// now get the text from the response
			String sHTML1 = this.parseHtmlFromEntity(entity1);			
			if(sHTML1.length() == 0)
			{
				Log.e(LOG_LOGINPROCESS, "error parsing HTML1");			
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
					{				
						this.LogoutElearning(client);
						return null;
					}
			}
			// look for "Academic" link, which will have 3 hidden form values we need to capture
			ArrayList<BasicNameValuePair> listParams1 = null;
			int nIndex= sHTML1.indexOf("Academic");
			if(nIndex> 0)
			{
				listParams1 = this.parseNameValueFromText(nIndex, "name =\"", "\"", "value =\"", "\"", sHTML1, 3);				
			}
			
			if(listParams1 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error parsing parameters");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}			
			}
														
			for(int i = 0; i < listParams1.size(); i++)
				Log.d(LOG_CONNECTION, "R1: name: " + listParams1.get(i).getName() + "  value: " + listParams1.get(i).getValue());
			
			/// clean up 1st page variables to free memory? or reuse?
			response1 = null;
			//entity1.consumeContent();    // todo
			sHTML1 = "";			
			
			//
			// second page
			//
			Log.i(LOG_CONNECTION, " -- About to make second call -- ");
			HttpPost httpost = new HttpPost("https://elearning.utdallas.edu/webct/entryPage.dowebct");
	
			// create list for parameters for logging in			
			httpost.setEntity(new UrlEncodedFormEntity(listParams1, HTTP.UTF_8));
			HttpResponse response2 = client.execute(httpost);
			HttpEntity entity2 = response2.getEntity();
			if(entity2 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error on second page response");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}			
			
			
			// look for   function submitLogin()   and the specified parameters after that to submit
			Log.i(LOG_CONNECTION, "-- about to parse response2 to get parameters --");
			sHTML1 = this.parseHtmlFromEntity(entity2);
			listParams1 = new ArrayList<BasicNameValuePair>();
			nIndex= sHTML1.indexOf("function submitLogin()");
			if(nIndex > 0)
			{
				listParams1 = this.parseNameValueFromText(nIndex, "document.vistaInsEntryForm.", ".", "value = \"", "\"", sHTML1, 4);
			}
			else
			{
				Log.e(LOG_LOGINPROCESS, "error making it to the second page, couldn't find the submitLogin func on the html loaded");
				
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			if(listParams1 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error parsing params from second page for third page");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			for(int i = 0; i < listParams1.size(); i++)
				Log.d(LOG_CONNECTION, "R2: name: " + listParams1.get(i).getName() + "  value: " + listParams1.get(i).getValue());
	
			
			//entity2.consumeContent();
			
			//
			// call to third page - /webct/logonDisplay.dowebct
			//
			HttpPost httpost3 = new HttpPost("https://elearning.utdallas.edu/webct/logonDisplay.dowebct");
			Log.i(LOG_CONNECTION, " -- About to make third call -- ");
			httpost3.setEntity(new UrlEncodedFormEntity(listParams1, HTTP.UTF_8));
			HttpResponse response3 = client.execute(httpost3);
			HttpEntity entity3 = response3.getEntity();
			if(entity3 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error on third page response");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			// look for '<title>Log in to eLearning</title>' to verify we made it to the third page 
			nIndex = this.parseHtmlFromEntity(entity3).indexOf("<title>Log in to eLearning</title>");
			if(nIndex < 0)
			{
				Log.e(LOG_LOGINPROCESS, "error on third page response - 2");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			// we can use the same parameters as last submission ??? 
			// just add a couple more
			listParams1.add(new BasicNameValuePair("gotoid", "null"));
			//tz = (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000);
			listParams1.add(new BasicNameValuePair("timeZoneOffset", "6"));    // hardcoded to central tz
			listParams1.add(new BasicNameValuePair("webctid", getUsername()));
			listParams1.add(new BasicNameValuePair("password", getPassword()));
			
			
			
			for(int i = 0; i < listParams1.size(); i++)
				Log.d(LOG_CONNECTION, "R3: name: " + listParams1.get(i).getName() + "  value: " + listParams1.get(i).getValue());
			
			//entity3.consumeContent();
			
			
			//
			// fourth page -- /webct/authenticateUser.dowebct
			//
			Log.i(LOG_CONNECTION, " -- About to make fourth call -- actual login with user/pass --  ");
			
			HttpPost httpost4 = new HttpPost("https://elearning.utdallas.edu/webct/authenticateUser.dowebct");
			httpost4.setEntity(new UrlEncodedFormEntity(listParams1, HTTP.UTF_8));
			HttpResponse response4 = client.execute(httpost4);
			HttpEntity entity4 = response4.getEntity();
			if(entity4 == null)
			{
				Log.e(LOG_LOGINPROCESS, "error on fourth page response");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			// look for '<title>Blackboard Learning System</title>' to ensure we made it to the fourth page (logged in)
			nIndex = this.parseHtmlFromEntity(entity4).indexOf("<title>Blackboard Learning System</title>");
			if(nIndex < 0)
			{
				Log.e(LOG_LOGINPROCESS, "error on fourth page response - 2");
				if(nAttemptedLogins < LOGIN_ATTEMPTS)
					return LoginToElearning(++nAttemptedLogins, client);
				else
				{				
					this.LogoutElearning(client);
					return null;
				}
			}
			
			//entity4.consumeContent();
			
			Log.i(LOG_CONNECTION, "-- successfully logged in to eLearning --");
						
    	}
    	catch(Exception ex)
    	{
    		Log.e(LOG_CONNECTION, "LoginToElearning error: " + ex.getMessage());    		
    		return null;
    	}
    	
    	return client;
    }
    
    private boolean LogoutElearning(HttpClient client)
    {
    	boolean bSuccess = false;
    	try
    	{
    		/// now logout 
			// /webct/urw/lc5122011.tp0/logout.dowebct?insId=5122011&insName=Academic&glcid=URN:X-WEBCT-VISTA-V1:ffc0dca0-0ab4-0f47-0134-42f173422d1b
			HttpGet requestLO = new HttpGet("https://elearning.utdallas.edu/webct/urw/lc5122011.tp0/logout.dowebct?insId=5122011&insName=Academic&glcid=URN:X-WEBCT-VISTA-V1:ffc0dca0-0ab4-0f47-0134-42f173422d1b");
        	
    		// execute request for first page, which provides us with connection parameters
        	Log.i(LOG_CONNECTION, "-- logging out of eLearning --");
			client.execute(requestLO);
			
			client.getConnectionManager().closeIdleConnections(1, TimeUnit.MILLISECONDS);
			
			bSuccess = true;
    	}
    	catch(Exception ex)
    	{
    		Log.e(LOG_LOGINPROCESS, "Error logging out: " + ex.getMessage());
    	}
    	
    	return bSuccess;
    }
    
    
    private ArrayList<BasicNameValuePair> parseNameValueFromText(int nIndex, String sNameTemplate, String sNameEnd, String sValueTemplate, String sValueEnd, String sTextToParse, int nIterations )
    {
    	ArrayList<BasicNameValuePair> listNVP = null;
    	
    	try
    	{
    		listNVP = new ArrayList<BasicNameValuePair>();
    		int nCounter = 0;
    		while(nCounter < nIterations)
    		{
	    		// get name parameter
				nIndex = sTextToParse.indexOf(sNameTemplate, nIndex);
				// add the [ame ="] to get what is in the quotes after name
				nIndex += sNameTemplate.length();
				int nIndexEnd = sTextToParse.indexOf(sNameEnd, nIndex);
				String sName = sTextToParse.substring(nIndex, nIndexEnd);
				
				// special processing for first page 
				if(sName.equalsIgnoreCase("glcid1"))
					sName = "glcid";
				else if(sName.equalsIgnoreCase("insId1"))
					sName = "insId";
				else if(sName.equalsIgnoreCase("insName1"))
					sName = "insName";
	
				// get value parameter
				nIndex = sTextToParse.indexOf(sValueTemplate, nIndexEnd);
				// add the [alue ="] to get what is in the quotes after value
				nIndex += sValueTemplate.length();
				nIndexEnd = sTextToParse.indexOf(sValueEnd, nIndex);
				String sValue = sTextToParse.substring(nIndex , nIndexEnd);
				
				listNVP.add(new BasicNameValuePair(sName, sValue));
				nCounter++;
    		}
    	}
    	catch(Exception ex)
    	{
    		listNVP = null;
    	}
    	return listNVP;
    }
    
    private ArrayList<UniversityClass> parseUnivClassesFromText(int nIndex, String sTextToParse )
    {
    	ArrayList<UniversityClass> listClasses = null;
    	
    	try
    	{
    		listClasses = new ArrayList<UniversityClass>();
    		UniversityClass univClass = new UniversityClass();
    		
    		//since the class are at the bottom, just keep searching until you don't find alt=" anymore
    		nIndex = sTextToParse.indexOf("alt=\"", nIndex);
    		while(nIndex > 0)
    		{
    			univClass = new UniversityClass();
    			
	    		// find index of beginning
				nIndex = sTextToParse.indexOf("alt=\"", nIndex);
				// add the rest of the string to get what is in the quotes after it
				nIndex += "alt=\"".length();
				int nIndexEnd = sTextToParse.indexOf("\"", nIndex);
				String sWholeValue = sTextToParse.substring(nIndex, nIndexEnd);
				
				// string should be in format: SE 4485 001: Software Engineering Project - S11			
				if (sWholeValue.indexOf(":") > 0) {
					String sClassSpecs = sWholeValue.substring(0, sWholeValue.indexOf(":"));
					String sClassTitle = sWholeValue.substring(sWholeValue.indexOf(":")+1, sWholeValue.length());
					String[] sValueArray = sClassSpecs.split(" ");
					univClass.Prefix = sValueArray[0];
					univClass.ClassNumber = sValueArray[1];
					univClass.ClassSection = "." + sValueArray[2];
					univClass.Title = sClassTitle.substring(0, sClassTitle.indexOf("-")-1);
					univClass.Semester = sClassTitle.substring(sClassTitle.indexOf("-")+2, sClassTitle.length());
					listClasses.add(univClass);
				}		
				else
				{
					Log.e("PARSE_CLASSES", "error parsing class string: " + sWholeValue);
				}								

				// "advance counter" to next one
				nIndex = sTextToParse.indexOf("alt=\"", nIndex);
    		}
    	}
    	catch(Exception ex)
    	{
    		//listClasses = null;
    		Log.e("PARSE_CLASSES", "error");
    	}
    	return listClasses;
    }
    
    private String parseHtmlFromEntity(HttpEntity entity)
    {
    	String html = "";
    	try
    	{
			InputStream in = entity.getContent();			
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			StringBuilder str = new StringBuilder();
			String line = null;
			int count = 0;
			while ((line = reader.readLine()) != null && count < 10000000)		// todo: limit??
			{
				str.append(line);
				count++;
			}
			in.close();
			html = str.toString();
    	}
    	catch(Exception ex)
    	{
    		Log.e("PARSE_HTML_ENTITY", ex.getMessage());
    		html = "";
    	}
    	return html;
    }
    
    private int[] findDaysWithEvents(String sHTML) {
    	int[] dayArray = new int[31];
    	boolean blnOutOfDays = false;
    	
    	Log.i(LOG_CONNECTION, "Called findDaysWithEvents");
    	
//    	Log.i("PARSE_CALENDAR", sHTML.substring(sHTML.length()-2000, sHTML.length()-1000));
    	try
	    {    		
	    	sHTML = sHTML.substring(sHTML.indexOf("&amp;day=1&")-10, sHTML.length());
	    	
	    	String currentDay = "";
	    	
	    	for (int i=0; i<31; i++) {
	    		if (!blnOutOfDays) {
		    		// if not at the end of the month then get everything for one day
	    			try {
	    				if (sHTML.indexOf("&amp;day="+(i+2)) != -1) 
	    					currentDay = sHTML.substring(sHTML.indexOf("&amp;day="+(i+1)), sHTML.indexOf("&amp;day="+(i+2)));
		    		// otherwise get everything for the last day of the month
		    		} catch(Exception x) {
		    			try { 
		    				currentDay = sHTML.substring(sHTML.indexOf("&amp;day="+(i+1)), sHTML.indexOf("&amp;day=1", sHTML.indexOf("&amp;day="+(i+1))));
		    			}
		    			catch(Exception ex) {
		    				currentDay = sHTML.substring(sHTML.indexOf("&amp;day="+(i+1)), sHTML.indexOf("</ul>"));
		    			}
		    			blnOutOfDays = true;
		    		}    	
	    		} else {
	    			currentDay = "";
	    		}
	    		
	//    		Log.i(LOG_CONNECTION, currentDay);
	    		if (currentDay.length() > 0) {
	//    			Log.i(LOG_CONNECTION, "length=" + currentDay.length() + " " + currentDay);
	    			String[] testArray = currentDay.split("<li ");
	    			
	    			for (int j=1; j<testArray.length; j++) {
	//    				Log.i(LOG_CONNECTION, "testArray=" + testArray[j]);
	    				if (!testArray[j].contains("Weekly eLearning Maintenance")) {
	    					dayArray[i] = i+1;
	    				}
	    			}
	    		} else {
	    			dayArray[i] = 0;
	    		}
	    		
	    		currentDay = "";
	    	}
	    }
    	catch(Exception ex)
    	{
    		Log.e("PARSE_CALENDAR", ex.getMessage());
    	}
    	
    	return dayArray;
    }
      
    
    private ArrayList<UnivClassEvent> parseEventFromDay(ArrayList<UniversityClass> listClasses, String sHTML, Date dueDate) {
    	
    	ArrayList<UnivClassEvent> listEvents = new ArrayList<UnivClassEvent>();
    	String prefix="";
    	String class_number="";
    	String class_section="";   	
    	String strEvent = "";
		String strTime = "";
		String strClass = "";
		String hour = "";
		String minutes = "";
		
		
    	if (sHTML.indexOf("calendarlist ") > 0) {
    		try {
	    		sHTML = sHTML.substring(sHTML.indexOf("calendarlist "), sHTML.length());
	    		sHTML = sHTML.substring(sHTML.indexOf(">"), sHTML.length());
	
				String[] testArray = sHTML.split("<li>");
				
				// parse events
				for (int j=1; j<testArray.length; j++) {
//					Log.i(LOG_CONNECTION, "testArray=" + testArray[j]);
	
			    	strEvent = testArray[j].substring(testArray[j].indexOf("<h3"), testArray[j].indexOf("</h3>"));
			    	strEvent = strEvent.substring(strEvent.indexOf(">")+1, strEvent.length());
			    	Log.i("PARSE_EVENT", strEvent);
			    	
			    	testArray[j] = testArray[j].substring(testArray[j].indexOf("</h3>"), testArray[j].length());
			    	
			    	strTime = testArray[j].substring(testArray[j].indexOf("entrytime"), testArray[j].indexOf("</p>"));
			    	strTime = strTime.substring(strTime.indexOf(">")+1, strTime.indexOf(" ")+3);
			    	Log.i("PARSE_EVENT", strTime);
			    	
			    	testArray[j] = testArray[j].substring(testArray[j].indexOf(" />")+3, testArray[j].length());
			    	
			    	
			    	try {
			    		strClass = testArray[j].substring(0, testArray[j].indexOf("</p>")).trim();
			    	
			    		if (strClass.indexOf(":") != -1) {
					    	strClass = strClass.substring(0, strClass.indexOf(":"));
					    	Log.i("PARSE_EVENT", strClass);			
			
							String[] sValueArray = strClass.split(" ");
							prefix = sValueArray[0];
							class_number = sValueArray[1];
							class_section = "." + sValueArray[2];
			    		}
			    		else {
			    			strClass = "";
			    		}
			    	} 
			    	catch(Exception ex) {
			    		strClass = "";
			    	}
					
			    	
			    	UnivClassEvent uce = new UnivClassEvent();
					
					if (strTime.length() > 0) {
						hour = strTime.substring(0, strTime.indexOf(":"));
						if (strTime.contains("PM")){
							hour = String.valueOf((Integer.parseInt(hour) + 12));
						}
						
						if (hour.length()<2) {hour = "0" + hour;}
						
						minutes = strTime.substring(strTime.indexOf(":")+1, strTime.indexOf(" "));
						if (minutes.length()<2) {minutes = "0" + minutes;}
					}
					
					dueDate.setHours(Integer.parseInt(hour));
					dueDate.setMinutes(Integer.parseInt(minutes));
					uce.DueDate = dueDate;
					uce.Name = strEvent;
					
					if (strClass != "") {
						Cursor cursor = mDbHelper.getClass(prefix, class_number, class_section);
						startManagingCursor(cursor);
						cursor.moveToFirst();
						uce.ClassId = cursor.getLong(cursor.getColumnIndexOrThrow(CalDbAdapter.ROW_ID));
						cursor.close();
					}
					else {
						uce.ClassId = 0;
					}
				
					if(strEvent.contains("Assignment"))
				        uce.EventTypeId=4;
					else if(strEvent.contains("Project"))
				        uce.EventTypeId=2;
					else if(strEvent.contains("Test"))
				        uce.EventTypeId=2;
					else if(strEvent.contains("Quiz"))
				        uce.EventTypeId=3;
					else
				        uce.EventTypeId=1;						
					
					listEvents.add(uce);
			    	
				}				
    		}
			catch(Exception e)
			{
				Log.e("PARSE_EVENT", "Error parsing events for day " + dueDate + ".");
			}		
		} else {
			Log.e("PARSE_EVENT", "Error parsing events for day " + dueDate + ", nothing to parse.");
		}

    	return listEvents;    	
    	
    }
    
    private ArrayList<UnivClassEvent> parseEventsFromCalendar(ArrayList<UniversityClass> listClasses, String sHTML)
    {    	
    	ArrayList<UnivClassEvent> listEvents = new ArrayList<UnivClassEvent>();
    	
    	// remove the end portion of the html (the "Key:") which has all the classes listed
		// because we will be searching the html calendar for these classes
    	if (sHTML.indexOf("Key:") > 0)
    		sHTML = sHTML.substring(0, sHTML.indexOf("Key:"));
		
    	for(UniversityClass u: listClasses)
		{
			int start = sHTML.indexOf(u.Prefix + " " + u.ClassNumber + " " + u.ClassSection.replace(".", ""));
			Log.d("PARSE_EVENT", u.Prefix + " " + u.ClassNumber + " " + u.ClassSection.replace(".", ""));
			while( start > 0 )					
			{
				// parse the calendar event
				// 
				// example event
				//
				// <td valign="top"   class='' >
				// <a href="/webct/urw/lc5122011.tp0/viewDay.dowebct?month=4&amp;day=6&amp;year=2011" class="daylink">6</a>
				// <!-- list of entries -->
				// <ul>
				// <li >
				//<img src=".." width="10" alt="SE 4352 501: Software Architecture and Design - S11" title="SE 4352 501: Software Architecture and Design - S11" align="absmiddle" />
				//    <a href="J.." title="..">     (---- This <a> is not always there, only if there is a link to it on the class -----)
				//Project Two: SDMS Implementation Due
				//     </a>
				//</li>
				try
				{
					start = sHTML.indexOf("/>", start);
					start += 2;
					int end = sHTML.indexOf("</li>", start);
					
					// get date of event, which is above this line, ~330 characters
					int nDateIndex = start - 330;
					nDateIndex = sHTML.indexOf("viewDay.dowebct?", nDateIndex);
					if(nDateIndex > 0)
					{
						nDateIndex = sHTML.indexOf("month=", nDateIndex) + 6;
						String sMonth = sHTML.substring(nDateIndex, sHTML.indexOf("&", nDateIndex));
						//sMonth = String.valueOf(Integer.parseInt(sMonth) + 1);	/// add one because it was on a 0-index
						sMonth = String.valueOf(Integer.parseInt(sMonth));	
						nDateIndex = sHTML.indexOf("day=", nDateIndex) + 4;
						String sDay = sHTML.substring(nDateIndex, sHTML.indexOf("&", nDateIndex));
						nDateIndex = sHTML.indexOf("year=", nDateIndex) + 5;
						String sYear = sHTML.substring(nDateIndex, sHTML.indexOf("\"", nDateIndex));
																	
												
						int i = sHTML.indexOf("<a", start);  
						if(i > 0 && i < end)
						{
							// format for this event is: <a> Event </a> , so make a new start and end
							start = sHTML.indexOf(">", i);
							start++;
							end = sHTML.indexOf("</a", start);
						}
						String eventName = sHTML.substring(start, end).trim();
						Log.i("PARSE_EVENT", u.Prefix + " " + u.ClassNumber + " " + u.ClassSection + " found event: " + eventName + " on " + sMonth + "/" + sDay + "/" + sYear);
						
						UnivClassEvent uce = new UnivClassEvent();
						Date dueDate = new Date();
						dueDate.setDate(Integer.parseInt(sDay));
						dueDate.setMonth(Integer.parseInt(sMonth));
						dueDate.setYear(Integer.parseInt(sYear));
						uce.DueDate = dueDate;
						uce.Name = eventName;
						uce.ClassId = u.UniversityClassId;
					
						if(eventName.contains("Assignment"))
					        uce.EventTypeId=3;
						else if(eventName.contains("Project"))
					        uce.EventTypeId=1;
						else if(eventName.contains("Test"))
					        uce.EventTypeId=1;
						else if(eventName.contains("Quiz"))
					        uce.EventTypeId=2;
						else
					        uce.EventTypeId=4;						
						
						listEvents.add(uce);
					}
					else
					{
						Log.e("PARSE_EVENT", "Couldn't find/parse the date for: " + u.Prefix + " " + u.ClassNumber + " " + u.ClassSection);
						/// todo: tell user?
					}
					
					// advance counter -- there could be another event by this class
					start = sHTML.indexOf(u.Prefix + " " + u.ClassNumber + " " + u.ClassSection, start);
				}
				catch(Exception e)
				{
					Log.e("PARSE_EVENT", "Error parsing event for class " + u.Prefix + " " + u.ClassNumber + " " + u.ClassSection + ": " + e.getMessage());
					start = -1; /// ends the loop for this class : just go to next one  
				}
			}
			
		}
    	
    	return listEvents;
    }
    
    private String getUsername()
    {
    	if(username.length() > 0)
    		return username;
    	else
    	{
    		// get it from the preferences
    		username = prefs.getString("UserName", "");
    		
    		return username;
    	}
    }
    
	private String getPassword()
	{
		if(password.length() > 0)
    		return password;
    	else
    	{
    		// get it from the preferences
    		password = prefs.getString("PassWord", "");
    		
    		return password;
    	}
	}       
	
    private void setLastSyncText() {
    	String last_sync = "";
    	String status = "";
        TextView txtSync = (TextView) this.findViewById(R.id.txtPortalSyncTime);
        TextView txtStatus = (TextView) this.findViewById(R.id.txtPortalSyncSuccess);
        
    	try {
    		Cursor result;
			
			result = mDbHelper.getElearnLog();
						
			startManagingCursor(result);

			if(result.getCount() > 0)
			{
				result.moveToFirst();
				last_sync = result.getString(result.getColumnIndexOrThrow(CalDbAdapter.ELEARN_LOG_DATE));
				status = result.getString(result.getColumnIndexOrThrow(CalDbAdapter.ELEARN_LOG_STATUS));
				
				txtSync.setText("  " + last_sync);
		        txtStatus.setText("  " + status);
			}
			
			result.close();
    	} catch(Exception e) {
    		txtSync.setText(last_sync);
	        txtStatus.setText(status);
    	}
    }
}